<template>
  <div style="display:flex; gap:16px; align-items:flex-start;">
    <div style="flex:1;">
      <a-card>
        <template #title>
          <div style="display:flex;gap:8px;align-items:center">
            <a-input v-model:value="keyword" allow-clear style="width:240px" placeholder="搜索标题/摘要/关键字" @pressEnter="onSearch" />
            <a-select v-model:value="status" style="width:120px" @change="onSearch">
              <a-select-option :value="-1">全部</a-select-option>
              <a-select-option :value="1">已发布</a-select-option>
              <a-select-option :value="0">草稿</a-select-option>
            </a-select>
            <a-button type="primary" @click="onSearch">查询</a-button>
          </div>
        </template>

        <a-table
          :data-source="list"
          :loading="loading"
          :pagination="false"
          row-key="id"
        >
          <a-table-column key="id" title="ID" data-index="id" width="80" />
          <a-table-column key="title" title="标题" data-index="title" />
          <a-table-column key="categoryName" title="分类" data-index="categoryName" width="120" />
          <a-table-column key="viewCount" title="阅读" data-index="viewCount" width="90" />
          <a-table-column key="likeCount" title="点赞" data-index="likeCount" width="90" />
          <a-table-column key="commentCount" title="评论" data-index="commentCount" width="90" />
          <a-table-column key="status" title="状态" width="90">
            <template #default="{ record }">
              <a-tag :color="record.status === 1 ? 'green' : 'default'">{{ record.status === 1 ? '已发布' : '草稿' }}</a-tag>
            </template>
          </a-table-column>
          <a-table-column key="createTime" title="创建时间" data-index="createTime" width="180" />
          <a-table-column key="actions" title="操作" width="260">
            <template #default="{ record }">
              <a-space>
                <a @click="preview(record.id)">预览</a>
                <a v-if="hasAny(['article:update'])" @click="edit(record.id)">编辑</a>
                <a v-if="hasAny(['oss:manage'])" @click="showRefs(record.id)">查看引用</a>
                <a-popconfirm v-if="hasAny(['article:delete'])" title="确认删除该文章？" @confirm="() => doDelete(record.id)">
                  <a>删除</a>
                </a-popconfirm>
              </a-space>
            </template>
          </a-table-column>
        </a-table>

        <div style="margin-top:12px;text-align:right">
          <a-pagination
            :current="pageNo"
            :page-size="pageSize"
            :total="total"
            @change="onPageChange"
            @showSizeChange="onSizeChange"
            show-size-changer
            :page-size-options="['10','20','50']"
          />
        </div>
      </a-card>
    </div>
    <div style="width:320px; position:sticky; top:16px;">
      <a-card title="引用的资源" size="small">
        <div v-if="coverUrl" class="item">
          <div class="title">封面</div>
          <a-image :src="coverUrl" :width="120" />
          <div class="url">{{ coverUrl }}</div>
          <a @click="openOss()">去管理</a>
        </div>
        <a-divider />
        <div class="title">正文图片 ({{ contentImages.length }})</div>
        <div v-if="contentImages.length===0" class="muted">暂无</div>
        <div v-else class="images">
          <div v-for="u in contentImages" :key="u" class="img-item">
            <a-image :src="u" :width="80" />
            <div class="url ellipsis" :title="u">{{ u }}</div>
          </div>
        </div>
        <a @click="openOss()" v-if="contentImages.length">去管理</a>
      </a-card>
      <a-card title="文章编辑" size="small" style="margin-top:12px">
        <a-button v-if="hasAny(['article:write'])" type="primary" block @click="edit()">新建文章</a-button>
        <a-modal v-model:open="editVisible" title="文章编辑" width="800px" @ok="submitEdit">
          <a-form layout="vertical">
            <a-form-item label="标题" required>
              <a-input v-model:value="form.title" placeholder="请输入标题" />
            </a-form-item>
            <a-form-item label="摘要">
              <a-textarea v-model:value="form.summary" :rows="3" placeholder="摘要" />
            </a-form-item>
            <a-form-item label="封面">
              <SmartUpload v-model="form.coverImage" file-type="image" :max-count="1" />
            </a-form-item>
            <a-form-item label="分类">
              <a-select v-model:value="form.categoryId" allow-clear placeholder="选择分类">
                <a-select-option v-for="c in categories" :key="c.id" :value="c.id">{{ c.name }}</a-select-option>
              </a-select>
            </a-form-item>
            <a-form-item label="状态">
              <a-select v-model:value="form.status">
                <a-select-option :value="0">草稿</a-select-option>
                <a-select-option :value="1">已发布</a-select-option>
              </a-select>
            </a-form-item>
            <a-form-item label="标签">
              <a-select
                v-model:value="form.tagIds"
                mode="multiple"
                allow-clear
                placeholder="选择标签"
                show-search
                :filter-option="false"
                @search="onSearchTag"
              >
                <a-select-option v-for="t in tagOptions" :key="t.id" :value="t.id">{{ t.name }}</a-select-option>
              </a-select>
            </a-form-item>
            <a-form-item label="内容 (Markdown)">
              <div @paste="onEditorPaste" @drop.prevent="onEditorDrop" @dragover.prevent>
                <SafeMarkdownEditor v-model="form.content" :style="{ height: editorHeight }" />
              </div>
              <div style="margin-top:8px">
                <a-space>
                  <SmartUpload file-type="image" :multiple="true" :max-count="8" @uploaded="insertImageMarkdown" />
                  <span style="color:rgba(0,0,0,0.45)">粘贴/拖拽/上传图片将自动插入 Markdown</span>
                </a-space>
              </div>
            </a-form-item>
          </a-form>
        </a-modal>
      </a-card>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { extractImageUrls } from '@/utils/content'
import { adminPageArticles, adminDeleteArticle, adminGetArticleDetail, adminCreateArticle, adminUpdateArticle } from '@/api/admin/modules/articles'
import { fetchCategories, fetchTags } from '@/api/public/articles'
import type { CategoryVO, TagVO } from '@/types/api'
import { uploadFile } from '@/api/upload'
import { message } from 'ant-design-vue'
import SmartUpload from '@/components/SmartUpload.vue'
import VMdEditor from '@kangc/v-md-editor'
import { usePerm } from '@/composables/usePerm'

// 提示：此处假设页面已有当前编辑的文章数据状态（示例使用事件或全局 store 获取）
// 通过自定事件 window.currentArticle 传递当前编辑/选中的文章数据（仅用于演示集成，真实项目应对接实际数据流）

const router = useRouter();
const current = ref<{ coverImage?: string; content?: string } | null>(null);
const loading = ref(false);
const list = ref<any[]>([]);
const pageNo = ref(1);
const pageSize = ref(10);
const total = ref(0);
const keyword = ref('');
const status = ref<number>(-1);
const editVisible = ref(false);
const editingId = ref<number | null>(null);
const form = ref({ title: '', summary: '', coverImage: '', categoryId: undefined as number | undefined, status: 0, tagIds: [] as number[], content: '' });
const categories = ref<CategoryVO[]>([]);
const tags = ref<TagVO[]>([]);
const tagOptions = ref<TagVO[]>([]);
const editorHeight = 'min(60vh, 560px)';
const { hasAny } = usePerm()

// 临时：监听来自全局的事件以更新当前文章（你可替换为你的实际数据来源）
;(window as any).__setCurrentArticle = (data: any) => { current.value = data }

const coverUrl = computed(() => current.value?.coverImage || '')
const contentImages = computed(() => extractImageUrls(current.value?.content))

function openOss() { router.push({ name: 'AdminOss' }) }

async function load() {
  loading.value = true
  try {
    const { data } = await adminPageArticles({
      pageNo: pageNo.value,
      pageSize: pageSize.value,
      keyword: keyword.value || undefined,
      status: status.value === -1 ? undefined : status.value
    } as any)
    list.value = data.records || []
    total.value = data.total || 0
  } finally {
    loading.value = false
  }
}

function onSearch() { pageNo.value = 1; load() }
function onPageChange(p: number) { pageNo.value = p; load() }
function onSizeChange(_: number, size: number) { pageSize.value = size; pageNo.value = 1; load() }

function preview(id: number) {
  router.push({ name: 'ArticleDetail', params: { id: String(id) } })
}

function edit(id?: number) {
  if (id) {
    editingId.value = id
    adminGetArticleDetail(id).then(({ data }) => {
      form.value = {
        title: data.title || '',
        summary: data.summary || '',
        coverImage: data.coverImage || '',
        categoryId: data.categoryId || undefined,
        status:  data.status ?? 0,
        tagIds:  [],
        content: data.content || ''
      }
      // 将详情中的标签名映射为 tagIds
      const tagNames = (data.tags || '').split(',').map(s => s.trim()).filter(Boolean)
      if (tagNames.length && tags.value?.length) {
        form.value.tagIds = tags.value.filter(t => tagNames.includes(t.name)).map(t => t.id)
      }
      editVisible.value = true
      // 同步右侧引用预览
      current.value = { coverImage: form.value.coverImage, content: form.value.content }
    })
  } else {
    editingId.value = null
    form.value = { title: '', summary: '', coverImage: '', categoryId: undefined, status: 0, tagIds: [], content: '' }
    editVisible.value = true
    current.value = { coverImage: '', content: '' }
  }
}

async function submitEdit() {
  if (!form.value.title || !form.value.title.trim()) {
    message.warning('请输入标题')
    return
  }
  const payload = { ...form.value }
  if (editingId.value) await adminUpdateArticle(editingId.value, payload)
  else await adminCreateArticle(payload)
  editVisible.value = false
  load()
}

async function onPickCover(e: Event) {
  const input = e.target as HTMLInputElement
  if (!input.files || !input.files.length) return
  const f = input.files[0]
  const { url } = await uploadFile(f)
  form.value.coverImage = url
}

function insertImageMarkdown(url: string) {
  const md = `\n\n![image](${url})\n\n`
  form.value.content = (form.value.content || '') + md
}

async function onUploadContentImage(e: Event) {
  const input = e.target as HTMLInputElement
  if (!input.files || !input.files.length) return
  const f = input.files[0]
  const { url } = await uploadFile(f)
  insertImageMarkdown(url)
  input.value = ''
}

function filesFromDataTransfer(dt: DataTransfer): File[] {
  const files: File[] = []
  if (!dt?.items) return files
  for (let i = 0; i < dt.items.length; i++) {
    const it = dt.items[i]
    if (it.kind === 'file') {
      const f = it.getAsFile()
      if (f) files.push(f)
    }
  }
  return files
}

async function handlePasteOrDropFiles(fileList: File[]) {
  for (const f of fileList) {
    if (f.type.startsWith('image/')) {
      const { url } = await uploadFile(f)
      insertImageMarkdown(url)
    }
  }
}

async function onEditorPaste(e: ClipboardEvent) {
  const items = e.clipboardData?.items
  const files: File[] = []
  if (items) {
    for (let i = 0; i < items.length; i++) {
      const it = items[i]
      if (it.kind === 'file') {
        const f = it.getAsFile()
        if (f) files.push(f)
      }
    }
  }
  if (files.length) {
    e.preventDefault()
    await handlePasteOrDropFiles(files)
  }
}

async function onEditorDrop(e: DragEvent) {
  const dt = e.dataTransfer
  if (!dt) return
  const files = filesFromDataTransfer(dt)
  if (files.length) {
    await handlePasteOrDropFiles(files)
  }
}

function onSearchTag(q: string) {
  if (!q) { tagOptions.value = tags.value; return }
  const s = q.toLowerCase()
  tagOptions.value = tags.value.filter(t => t.name.toLowerCase().includes(s))
}

onMounted(async () => {
  const [c, t] = await Promise.all([fetchCategories(), fetchTags()])
  categories.value = c.data || []
  tags.value = t.data || []
  tagOptions.value = tags.value
})

async function showRefs(id: number) {
  const { data } = await adminGetArticleDetail(id)
  current.value = { coverImage: data.coverImage, content: data.content }
}

async function doDelete(id: number) {
  const resp = await adminDeleteArticle(id)
  if (resp.code === 0) {
    load()
  }
}

load()
</script>

<style scoped>
.item { display: grid; gap: 6px; }
.title { font-weight: 600; margin-bottom: 6px; }
.muted { color: rgba(0,0,0,0.45); }
.images { display: grid; gap: 8px; grid-template-columns: 1fr; }
.img-item { display: grid; grid-template-columns: 80px 1fr; gap: 6px; align-items: center; }
.url { font-size: 12px; color: rgba(0,0,0,0.6); word-break: break-all; }
.ellipsis { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
</style>


